home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / prog_gen / freeli10.zip / FREELIB2.ASX < prev    next >
Text File  |  1996-04-20  |  61KB  |  2,223 lines

  1. ~~~C_STR1
  2. Ideal
  3.  
  4. Public      strlen,strcpy,strcat,strcmp
  5.  
  6. Model Tiny
  7. CodeSeg
  8. P186
  9.  
  10. ;****************** strlen() -- Get length of string
  11. ;int strlen(char *strp);
  12.  
  13. strp        equ bp+4
  14.  
  15. Proc        strlen
  16.  
  17.             push bp                 ;Set up stack frame
  18.             mov bp,sp
  19.             push si                 ;Save SI
  20.  
  21.             mov si,[strp]           ;SI = string pointer
  22.  
  23. p1_loop:    lodsb                   ;Load char
  24.             test al,al              ;Loop while not zero
  25.             jnz p1_loop
  26.  
  27.             sub si,[strp]           ;AX = length
  28.             dec si
  29.             mov ax,si
  30.  
  31.             pop si                  ;Restore SI
  32.             pop bp                  ;Delete stack frame
  33.             ret 2                   ;Return
  34.  
  35. EndP        strlen
  36.  
  37. ;****************** strcpy() -- Copy a string
  38. ;void strcpy(char *str1, char *str2);
  39.  
  40. str1        equ bp+6
  41. str2        equ bp+4
  42.  
  43. Proc        strcpy
  44.  
  45.             push bp                 ;Set up stack frame
  46.             mov bp,sp
  47.             pusha                   ;Save all registers
  48.  
  49.             mov si,[str2]           ;SI = source
  50.             mov di,[str1]           ;DI = destination
  51.  
  52. p2_loop:    lodsb                   ;Load char
  53.             mov [di],al             ;Store char
  54.             inc di
  55.             test al,al              ;Loop while not zero
  56.             jnz p2_loop
  57.  
  58.             popa                    ;Restore registers
  59.             pop bp                  ;Delete stack frame
  60.             ret 4                   ;Return
  61.  
  62. EndP        strcpy
  63.  
  64. ;****************** strcat() -- Concatenate strings
  65. ;void strcat(char *str1, char *str2);
  66.  
  67. str1        equ bp+6
  68. str2        equ bp+4
  69.  
  70. Proc        strcat
  71.  
  72.             push bp                 ;Set up stack frame
  73.             mov bp,sp
  74.             pusha                   ;Save all registers
  75.  
  76.             mov si,[str1]           ;SI = destination
  77.  
  78. p3_cloop:   lodsb                   ;Load char
  79.             test al,al              ;Loop while not zero
  80.             jnz p3_cloop
  81.  
  82.             mov di,si               ;DI = destination
  83.             mov si,[str2]           ;SI = source
  84.             dec di
  85.  
  86. p3_loop:    lodsb                   ;Load char
  87.             mov [di],al             ;Store char
  88.             inc di
  89.             test al,al              ;Loop while not zero
  90.             jnz p3_loop
  91.  
  92.             popa                    ;Restore registers
  93.             pop bp                  ;Delete stack frame
  94.             ret 4                   ;Return
  95.  
  96. EndP        strcat
  97.  
  98. ;****************** strcmp() -- Compare strings
  99. ;void strcmp(char *str1, char *str2);
  100.  
  101. str1        equ bp+6
  102. str2        equ bp+4
  103.  
  104. Proc        strcmp
  105.  
  106.             push bp                 ;Set up stack frame
  107.             mov bp,sp
  108.             push si di              ;Save registers
  109.  
  110.             mov si,[str1]           ;SI = source
  111.             mov di,[str2]           ;DI = destination
  112.  
  113. p4_loop:    lodsb                   ;Load char 1
  114.             mov ah,[di]             ;Load char 2
  115.             inc di
  116.             cmp al,ah               ;Not equal?
  117.             jne p4_nope
  118.             test al,al              ;Loop while not zero
  119.             jnz p4_loop
  120.  
  121.             xor ax,ax               ;Equal, return 0
  122. p4_done:    pop di si               ;Restore registers
  123.             pop bp                  ;Delete stack frame
  124.             ret 4                   ;Return
  125.  
  126. p4_nope:    sub al,ah               ;Not equal, return difference
  127.             mov ah,0                ;in first unequal position
  128.             sbb ah,0
  129.             jmp p4_done
  130.  
  131. EndP        strcmp
  132.  
  133. End
  134.  
  135. ~~~C_STR2
  136. Ideal
  137.  
  138. Extrn       strlen:near
  139. Public      strchr,strstr
  140.  
  141. Model Tiny
  142. CodeSeg
  143. P186
  144.  
  145. ;****************** strchr() -- Search string for char
  146. ;int strchr(char *strp, int chr);
  147.  
  148. strp        equ bp+6
  149. chr         equ bp+4
  150.  
  151. Proc        strchr
  152.  
  153.             push bp                 ;Set up stack frame
  154.             mov bp,sp
  155.             push si                 ;Save SI
  156.  
  157.             mov si,[strp]           ;SI = string pointer
  158.             mov ah,[chr]            ;AH = char
  159.  
  160. p1_loop:    lodsb                   ;Load char
  161.             test al,al              ;Null, not found
  162.             jz p1_nope
  163.             cmp al,ah               ;Loop while not equal
  164.             jne p1_loop
  165.  
  166.             sub si,[strp]           ;AX = position of char
  167.             dec si
  168.             mov ax,si
  169.  
  170. p1_done:    pop si                  ;Restore SI
  171.             pop bp                  ;Delete stack frame
  172.             ret 4                   ;Return
  173.  
  174. p1_nope:    mov ax,-1               ;Not found, return -1
  175.             jmp p1_done
  176.  
  177. EndP        strchr
  178.  
  179. ;****************** strstr() -- Search string for substring
  180. ;int strstr(char *strp, char *subp);
  181.  
  182. strp        equ bp+6
  183. subp        equ bp+4
  184.  
  185. Proc        strstr
  186.  
  187.             push bp                 ;Set up stack frame
  188.             mov bp,sp
  189.             push es                 ;Save registers
  190.             pusha
  191.  
  192.             push ds                 ;ES = DS
  193.             pop es
  194.  
  195.             mov si,[strp]           ;SI = string pointer
  196.             mov bx,[subp]           ;BX = substring pointer
  197.             push bx                 ;Get length of substring
  198.             call strlen             ;into DX
  199.             mov dx,ax
  200.             mov ah,[bx]             ;AH = first char
  201.  
  202. p3_loop:    lodsb                   ;Load char
  203.             test al,al              ;Null, not found
  204.             jz p3_nope
  205.             cmp al,ah               ;Loop while not equal
  206.             jne p3_loop
  207.  
  208.             mov cx,dx               ;CX = length
  209.             mov di,bx               ;DI = substring
  210.             push si                 ;Save SI
  211.             dec si                  ;Push back char
  212.             repe cmpsb              ;Compare strings
  213.             pop si                  ;Restore SI
  214.             jne p3_loop             ;Loop if not equal
  215.  
  216.             sub si,[strp]           ;AX = position of char
  217.             dec si
  218.             mov es,si               ;Sneaky: save it in ES
  219.  
  220. p3_done:    popa                    ;Restore registers
  221.             mov ax,es               ;Return value in AX
  222.             pop es
  223.             pop bp                  ;Delete stack frame
  224.             ret 4                   ;Return
  225.  
  226. p3_nope:    mov ax,-1               ;Not found, return -1
  227.             mov es,ax
  228.             jmp p3_done
  229.  
  230. EndP        strstr
  231.  
  232. End
  233.  
  234. ~~~C_STR3
  235. Ideal
  236.  
  237. Public      stricmp,strlwr,strupr
  238.  
  239. Model Tiny
  240. CodeSeg
  241. P186
  242.  
  243. ;****************** stricmp() -- Compare strings, case insensitive
  244. ;void stricmp(char *str1, char *str2);
  245.  
  246. str1        equ bp+6
  247. str2        equ bp+4
  248.  
  249. Proc        stricmp
  250.  
  251.             push bp                 ;Set up stack frame
  252.             mov bp,sp
  253.             push si di              ;Save registers
  254.  
  255.             mov si,[str1]           ;SI = source
  256.             mov di,[str2]           ;DI = destination
  257.  
  258. p1_loop:    lodsb                   ;Load char 1
  259.             mov ah,[di]             ;Load char 2
  260.             inc di
  261.  
  262.             cmp al,'a'              ;Convert AL to uppercase
  263.             jb p1_setAH
  264.             cmp al,'z'
  265.             ja p1_setAH
  266.             sub al,20h
  267.  
  268. p1_setAH:   cmp ah,'a'              ;Convert AH to uppercase
  269.             jb p1_comp
  270.             cmp ah,'z'
  271.             ja p1_comp
  272.             sub ah,20h
  273.  
  274. p1_comp:    cmp al,ah               ;Equal?
  275.             jne p1_nope
  276.             test al,al              ;Loop while not zero
  277.             jnz p1_loop
  278.  
  279.             inc ax                  ;Equal, return 1
  280.  
  281. p1_done:    pop di si               ;Restore registers
  282.             pop bp                  ;Delete stack frame
  283.             ret 4                   ;Return
  284.  
  285. p1_nope:    xor ax,ax               ;Not equal, return 0
  286.             jmp p1_done
  287.  
  288. EndP        stricmp
  289.  
  290. ;****************** strlwr() -- Convert string to lowercase
  291. ;int strlwr(char *strp);
  292.  
  293. strp        equ bp+4
  294.  
  295. Proc        strlwr
  296.  
  297.             push bp                 ;Set up stack frame
  298.             mov bp,sp
  299.             pusha                   ;Save registers
  300.  
  301.             mov si,[strp]           ;SI = string pointer
  302.  
  303. p2_loop:    lodsb                   ;Load char
  304.             test al,al              ;Check for null
  305.             jz p2_done
  306.             cmp al,'A'              ;Check for uppercase
  307.             jb p2_loop
  308.             cmp al,'Z'
  309.             ja p2_loop
  310.             add al,20h              ;Convert to lowercase
  311.             mov [si-1],al           ;Store char
  312.             jmp p2_loop
  313.  
  314. p2_done:    popa                    ;Restore registers
  315.             pop bp                  ;Delete stack frame
  316.             ret 2                   ;Return
  317.  
  318. EndP        strlwr
  319.  
  320. ;****************** strupr() -- Convert string to uppercase
  321. ;int strupr(char *strp);
  322.  
  323. strp        equ bp+4
  324.  
  325. Proc        strupr
  326.  
  327.             push bp                 ;Set up stack frame
  328.             mov bp,sp
  329.             pusha                   ;Save registers
  330.  
  331.             mov si,[strp]           ;SI = string pointer
  332.  
  333. p3_loop:    lodsb                   ;Load char
  334.             test al,al              ;Check for null
  335.             jz p3_done
  336.             cmp al,'a'              ;Check for lowercase
  337.             jb p3_loop
  338.             cmp al,'z'
  339.             ja p3_loop
  340.             sub al,20h              ;Convert to uppercase
  341.             mov [si-1],al           ;Store char
  342.             jmp p3_loop
  343.  
  344. p3_done:    popa                    ;Restore registers
  345.             pop bp                  ;Delete stack frame
  346.             ret 2                   ;Return
  347.  
  348. EndP        strupr
  349.  
  350. End
  351.  
  352. ~~~C_STR4
  353. Ideal
  354.  
  355. Public      strrtrim,strltrim
  356.  
  357. Model Tiny
  358. CodeSeg
  359. P186
  360.  
  361. ;****************** strrtrim() -- Trim trailing spaces off a string
  362. ;int strrtrim(char *strp);
  363.  
  364. strp        equ bp+4
  365.  
  366. Proc        strrtrim
  367.  
  368.             push bp                 ;Set up stack frame
  369.             mov bp,sp
  370.             pusha                   ;Save registers
  371.  
  372.             mov si,[strp]           ;SI = string pointer
  373.             mov di,si               ;DI = SI
  374.  
  375. p1_loop:    lodsb                   ;Load char
  376.             test al,al              ;Check for null
  377.             jz p1_done
  378.             cmp al,' '              ;Check for space
  379.             je p1_loop
  380.             mov di,si               ;Set pointer
  381.             jmp p1_loop
  382.  
  383. p1_done:    popa                    ;Restore registers
  384.             pop bp                  ;Delete stack frame
  385.             ret 2                   ;Return
  386.  
  387. EndP        strrtrim
  388.  
  389. ;****************** strltrim() -- Trim leading spaces off a string
  390. ;int strltrim(char *strp);
  391.  
  392. strp        equ bp+4
  393.  
  394. Proc        strltrim
  395.  
  396.             push bp                 ;Set up stack frame
  397.             mov bp,sp
  398.             pusha                   ;Save registers
  399.  
  400.             mov si,[strp]           ;SI, DI = string pointer
  401.             mov di,si
  402.  
  403. p2_loop:    lodsb                   ;Load char
  404.             test al,al              ;Check for null
  405.             jz p2_cont
  406.             cmp al,' '              ;Loop while space
  407.             je p2_loop
  408.  
  409. p2_cont:    dec si                  ;Move back one char
  410.             cmp si,di               ;No spaces, quit
  411.             je p2_done
  412.  
  413. p2_cloop:   lodsb                   ;Shift the string over
  414.             mov [di],al
  415.             inc di
  416.             test al,al
  417.             jnz p2_cloop
  418.  
  419. p2_done:    popa                    ;Restore registers
  420.             pop bp                  ;Delete stack frame
  421.             ret 2                   ;Return
  422.  
  423. EndP        strltrim
  424.  
  425. End
  426.  
  427. ~~~C_MEM1
  428. Ideal
  429.  
  430. Public      memcpy,memset
  431.  
  432. Model Tiny
  433. CodeSeg
  434. P186
  435.  
  436. ;****************** memcpy() -- Copy memory block
  437. ;void memcpy(void *p1, void *p2, int nbytes);
  438.  
  439. p1          equ bp+8
  440. p2          equ bp+6
  441. nbytes      equ bp+4
  442.  
  443. Proc        memcpy
  444.  
  445.             push bp                 ;Set up stack frame
  446.             mov bp,sp
  447.             push es                 ;Save registers
  448.             pusha
  449.  
  450.             push ds                 ;ES = DS
  451.             pop es
  452.  
  453.             mov si,[p2]             ;SI = source
  454.             mov di,[p1]             ;DI = destination
  455.             mov cx,[nbytes]         ;CX = count
  456.  
  457.             cmp di,si               ;Make forward moves
  458.             jb p1_go                ;in reverse
  459.             je p1_done
  460.  
  461.             std                     ;Set direction flag
  462.             add si,cx               ;Move offsets to end
  463.             add di,cx
  464.             dec si
  465.             dec di
  466.  
  467. p1_go:      rep movsb               ;Copy memory
  468.  
  469. p1_done:    cld                     ;Clear direction flag
  470.             popa                    ;Restore registers
  471.             pop es
  472.             pop bp                  ;Delete stack frame
  473.             ret 6                   ;Return
  474.  
  475. EndP        memcpy
  476.  
  477. ;****************** memset() -- Set memory block
  478. ;void memset(void *ptr, int nbytes, int chr);
  479.  
  480. ptr         equ bp+8
  481. nbytes      equ bp+6
  482. chr         equ bp+4
  483.  
  484. Proc        memset
  485.  
  486.             push bp                 ;Set up stack frame
  487.             mov bp,sp
  488.             push es                 ;Save registers
  489.             pusha
  490.  
  491.             push ds                 ;ES = DS
  492.             pop es
  493.  
  494.             mov di,[ptr]            ;DI = block
  495.             mov cx,[nbytes]         ;CX = count
  496.             mov al,[chr]            ;AL = char
  497.             rep stosb               ;Set memory
  498.  
  499.             popa                    ;Restore registers
  500.             pop es
  501.             pop bp                  ;Delete stack frame
  502.             ret 6                   ;Return
  503.  
  504. EndP        memset
  505.  
  506. End
  507.  
  508. ~~~C_MEM2
  509. Ideal
  510.  
  511. Public      memcmp,memchr
  512.  
  513. Model Tiny
  514. CodeSeg
  515. P186
  516.  
  517. ;****************** memcmp() -- Compare memory blocks
  518. ;void memcmp(void *p1, void *p2, int nbytes);
  519.  
  520. p1          equ bp+8
  521. p2          equ bp+6
  522. nbytes      equ bp+4
  523.  
  524. Proc        memcmp
  525.  
  526.             push bp                 ;Set up stack frame
  527.             mov bp,sp
  528.             push es                 ;Save registers
  529.             push cx si di
  530.  
  531.             push ds                 ;ES = DS
  532.             pop es
  533.  
  534.             mov si,[p2]             ;SI = source
  535.             mov di,[p1]             ;DI = destination
  536.             mov cx,[nbytes]         ;CX = count
  537.             repe cmpsb              ;Compare memory
  538.  
  539.             mov ax,1                ;Assume equal
  540.             je p1_done              ;Jump if equal
  541.  
  542.             xor ax,ax               ;Not equal, return 0
  543.  
  544. p1_done:    pop di si cx            ;Restore registers
  545.             pop es
  546.             pop bp                  ;Delete stack frame
  547.             ret 6                   ;Return
  548.  
  549. EndP        memcmp
  550.  
  551. ;****************** memchr() -- Scan memory for char
  552. ;void memchr(void *ptr, int nbytes, int chr);
  553.  
  554. ptr         equ bp+8
  555. nbytes      equ bp+6
  556. chr         equ bp+4
  557.  
  558. Proc        memchr
  559.  
  560.             push bp                 ;Set up stack frame
  561.             mov bp,sp
  562.             push es                 ;Save registers
  563.             push cx si di
  564.  
  565.             push ds                 ;ES = DS
  566.             pop es
  567.  
  568.             mov di,[ptr]            ;DI = block
  569.             mov cx,[nbytes]         ;CX = count
  570.             mov al,[chr]            ;AL = char
  571.             repne scasb             ;Scan memory
  572.             jne p2_nope             ;Jump if not found
  573.  
  574.             sub di,[ptr]            ;AX = position of char
  575.             dec di
  576.             mov ax,di
  577.  
  578. p2_done:    pop di si cx            ;Restore registers
  579.             pop es
  580.             pop bp                  ;Delete stack frame
  581.             ret 6                   ;Return
  582.  
  583. p2_nope:    mov ax,-1               ;Not found, return -1
  584.             jmp p2_done
  585.  
  586. EndP        memchr
  587.  
  588. End
  589.  
  590. ~~~C_ISRCH
  591. Ideal
  592.  
  593. Public      isearch
  594.  
  595. Model Tiny
  596. P186
  597. CodeSeg
  598.  
  599. ;****************** isearch() -- Search a sorted array of integers
  600. ;int isearch(int *ary, int size, int elem);
  601.  
  602. ary         equ bp+8
  603. size        equ bp+6
  604. elem        equ bp+4
  605.  
  606. Proc        isearch
  607.  
  608.             push bp                 ;Set up stack frame
  609.             mov bp,sp
  610.             push bx cx dx si di     ;Save registers
  611.  
  612.             mov bx,[ary]            ;BX = array
  613.             xor cx,cx               ;CX = lower limit
  614.             mov dx,[size]           ;DX = upper limit
  615.             dec dx
  616.  
  617. p1_loop:    mov si,cx               ;SI = middle element
  618.             add si,dx
  619.             shr si,1
  620.             add si,si
  621.             mov ax,[bx+si]          ;Get element
  622.             shr si,1                ;Fix SI
  623.             cmp ax,[elem]           ;Check element
  624.             je p1_found             ;Equal?
  625.             jl p1_less              ;Too low?
  626.  
  627. p1_greater: mov di,si               ;Set first half
  628.             mov si,cx
  629.             jmp p1_cont
  630.  
  631. p1_less:    mov di,dx               ;Set second half
  632.             inc si
  633.  
  634. p1_cont:    cmp cx,dx               ;Min = Max, done
  635.             je p1_nope
  636.             mov cx,si               ;Set limits
  637.             mov dx,di
  638.             jmp p1_loop             ;Loop back
  639.  
  640. p1_found:   mov ax,si               ;AX = result
  641.  
  642. p1_done:    pop di si dx cx bx      ;Restore registers
  643.             pop bp                  ;Delete stack frame
  644.             ret 6                   ;Return
  645.  
  646. p1_nope:    mov ax,-1               ;Not found, return -1
  647.             jmp p1_done
  648.  
  649. EndP        isearch
  650.  
  651. End
  652.  
  653. ~~~C_LSRCH
  654. Ideal
  655.  
  656. Public      lsearch
  657.  
  658. Model Tiny
  659. P186
  660. CodeSeg
  661.  
  662. ;****************** lsearch() -- Search a sorted array of longs
  663. ;int lsearch(long *ary, int size, long elem);
  664.  
  665. ary         equ bp+10
  666. size        equ bp+8
  667. elem        equ bp+4
  668.  
  669. Proc        lsearch
  670.  
  671.             push bp                 ;Set up stack frame
  672.             mov bp,sp
  673.             push bx cx dx si di     ;Save registers
  674.  
  675.             mov bx,[ary]            ;BX = array
  676.             xor cx,cx               ;CX = lower limit
  677.             mov dx,[size]           ;DX = upper limit
  678.             dec dx
  679.  
  680. p2_loop:    mov si,cx               ;SI = middle element
  681.             add si,dx
  682.             shr si,1
  683.             shl si,2
  684.             mov ax,[bx+si]          ;Get element
  685.             mov di,[bx+si+2]
  686.             shr si,2                ;Fix SI
  687.  
  688.             cmp di,[elem+2]         ;Check high word
  689.             jl p2_less              ;Too low?
  690.             jg p2_greater           ;Too high?
  691.             cmp ax,[elem]           ;Check low word
  692.             je p2_found             ;Equal?
  693.             jl p2_less              ;Too low?
  694.  
  695. p2_greater: mov di,si               ;Set first half
  696.             mov si,cx
  697.             dec di
  698.             jmp p2_cont
  699.  
  700. p2_less:    mov di,dx               ;Set second half
  701.             inc si
  702.  
  703. p2_cont:    cmp cx,dx               ;Min = Max, done
  704.             je p2_nope
  705.             mov cx,si               ;Set limits
  706.             mov dx,di
  707.             jmp p2_loop             ;Loop back
  708.  
  709. p2_found:   mov ax,si               ;AX = result
  710.  
  711. p2_done:    pop di si dx cx bx      ;Restore registers
  712.             pop bp                  ;Delete stack frame
  713.             ret 8                   ;Return
  714.  
  715. p2_nope:    mov ax,-1               ;Not found, return -1
  716.             jmp p2_done
  717.  
  718. EndP        lsearch
  719.  
  720. End
  721.  
  722. ~~~C_XSRCH
  723. Ideal
  724.  
  725. Public      xsearch
  726.  
  727. Model Tiny
  728. P186
  729. CodeSeg
  730.  
  731. ;****************** xsearch() -- Search sorted array, generalized
  732. ;int xsearch(void **ary, int size, void *elem, void *func);
  733.  
  734. ary         equ bp+10
  735. size        equ bp+8
  736. elem        equ bp+6
  737. func        equ bp+4
  738.  
  739. Proc        xsearch
  740.  
  741.             push bp                 ;Set up stack frame
  742.             mov bp,sp
  743.             push bx cx dx si di     ;Save registers
  744.  
  745.             mov bx,[ary]            ;BX = array
  746.             xor cx,cx               ;CX = lower limit
  747.             mov dx,[size]           ;DX = upper limit
  748.             dec dx
  749.  
  750. p3_loop:    mov si,cx               ;SI = middle element
  751.             add si,dx
  752.             shr si,1
  753.             add si,si
  754.             mov ax,[bx+si]          ;Get element
  755.             shr si,1                ;Fix SI
  756.             push ax [elem]          ;Check element
  757.             call [word func]
  758.             test ax,ax
  759.             je p3_found             ;Equal?
  760.             jl p3_less              ;Too low?
  761.  
  762. p3_greater: mov di,si               ;Set first half
  763.             mov si,cx
  764.             jmp p3_cont
  765.  
  766. p3_less:    mov di,dx               ;Set second half
  767.             inc si
  768.  
  769. p3_cont:    cmp cx,dx               ;Min = Max, done
  770.             je p3_nope
  771.             mov cx,si               ;Set limits
  772.             mov dx,di
  773.             jmp p3_loop             ;Loop back
  774.  
  775. p3_found:   mov ax,si               ;AX = result
  776.  
  777. p3_done:    pop di si dx cx bx      ;Restore registers
  778.             pop bp                  ;Delete stack frame
  779.             ret 8                   ;Return
  780.  
  781. p3_nope:    mov ax,-1               ;Not found, return -1
  782.             jmp p3_done
  783.  
  784. EndP        xsearch
  785.  
  786. End
  787.  
  788. ~~~C_SSRCH
  789. Ideal
  790.  
  791. Extrn       strcmp:near
  792. Public      ssearch
  793.  
  794. Model Tiny
  795. P186
  796. CodeSeg
  797.  
  798. ;****************** ssearch() -- Search a sorted array of strings
  799. ;int ssearch(char **ary, int size, char *elem);
  800.  
  801. ary         equ bp+8
  802. size        equ bp+6
  803. elem        equ bp+4
  804.  
  805. Proc        ssearch
  806.  
  807.             push bp                 ;Set up stack frame
  808.             mov bp,sp
  809.             push bx cx dx si di     ;Save registers
  810.  
  811.             mov bx,[ary]            ;BX = array
  812.             xor cx,cx               ;CX = lower limit
  813.             mov dx,[size]           ;DX = upper limit
  814.             dec dx
  815.  
  816. p1_loop:    mov si,cx               ;SI = middle element
  817.             add si,dx
  818.             shr si,1
  819.             add si,si
  820.             mov ax,[bx+si]          ;Get element
  821.             shr si,1                ;Fix SI
  822.             push ax [elem]          ;Check element
  823.             call strcmp
  824.             test ax,ax
  825.             je p1_found             ;Equal?
  826.             jl p1_less              ;Too low?
  827.  
  828. p1_greater: mov di,si               ;Set first half
  829.             mov si,cx
  830.             jmp p1_cont
  831.  
  832. p1_less:    mov di,dx               ;Set second half
  833.             inc si
  834.  
  835. p1_cont:    cmp cx,dx               ;Min = Max, done
  836.             je p1_nope
  837.             mov cx,si               ;Set limits
  838.             mov dx,di
  839.             dec di
  840.             jmp p1_loop             ;Loop back
  841.  
  842. p1_found:   mov ax,si               ;AX = result
  843.  
  844. p1_done:    pop di si dx cx bx      ;Restore registers
  845.             pop bp                  ;Delete stack frame
  846.             ret 6                   ;Return
  847.  
  848. p1_nope:    mov ax,-1               ;Not found, return -1
  849.             jmp p1_done
  850.  
  851. EndP        ssearch
  852.  
  853. End
  854.  
  855. ~~~C_ISORT
  856. Ideal
  857.  
  858. Public      isort
  859.  
  860. Model Tiny
  861. P186
  862. CodeSeg
  863.  
  864. ;****************** isort() -- Sort an array of integers
  865. ;void isort(int *ary, int size);
  866.  
  867. ary         equ bp+6
  868. max         equ bp+4
  869.  
  870. Proc        isort
  871.  
  872.             push bp                 ;Set up stack frame
  873.             mov bp,sp
  874.             pusha                   ;Save all registers
  875.  
  876.             mov bx,[ary]            ;Call recursive routine
  877.             xor cx,cx
  878.             mov dx,[max]
  879.             dec dx
  880.             add dx,dx
  881.             call p1_qsort
  882.  
  883.             popa                    ;Restore registers
  884.             pop bp                  ;Delete stack frame
  885.             ret 4                   ;Return
  886.  
  887. p1_qsort:   cmp cx,dx               ;One element, return
  888.             je p1_ret
  889.             pusha
  890.  
  891.             mov ax,dx               ;Two elements, sort them
  892.             sub ax,cx
  893.             cmp ax,2
  894.             jne p1_cont
  895.  
  896.             mov si,cx               ;SI, DI = low, high
  897.             mov di,dx
  898.  
  899.             mov ax,[bx+si]          ;Check them
  900.             cmp ax,[bx+di]
  901.             jle p1_done
  902.  
  903.             xchg ax,[bx+di]         ;Switch them
  904.             mov [bx+si],ax
  905.             jmp p1_done
  906.  
  907. p1_cont:    mov si,cx               ;AX = middle element
  908.             add si,dx
  909.             shr si,2
  910.             add si,si
  911.             mov ax,[bx+si]
  912.  
  913.             mov si,cx               ;SI = low, DI = high
  914.             mov di,dx
  915.  
  916. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  917.             jge p1_loop2            ; SI < DX, advance SI
  918.             cmp ax,[bx+si]
  919.             jle p1_loop2
  920.             add si,2
  921.             jmp p1_loop
  922.  
  923. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  924.             jle p1_cont2            ; DI > CX, advance DI
  925.             cmp ax,[bx+di]
  926.             jge p1_cont2
  927.             sub di,2
  928.             jmp p1_loop2
  929.  
  930. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  931.             jge p1_rec
  932.  
  933.             push [bx+si]            ;Swap elements
  934.             push [bx+di]
  935.             pop [bx+si]
  936.             pop [bx+di]
  937.             add si,2                ;Advance SI, DI
  938.             sub di,2
  939.  
  940.             jmp p1_loop             ;Loop back
  941.  
  942. p1_rec:     cmp cx,si               ;If first half isn't empty,
  943.             je p1_skip1             ;recurse to sort it
  944.             xchg dx,di
  945.             call p1_qsort
  946.             xchg dx,di
  947.  
  948. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  949.             je p1_done              ;recurse to sort it
  950.             xchg cx,si
  951.             call p1_qsort
  952.             xchg cx,si
  953.  
  954. p1_done:    popa                    ;Restore registers
  955. p1_ret:     ret                     ;Return
  956.  
  957. EndP        isort
  958.  
  959. End
  960.  
  961. ~~~C_LSORT
  962. Ideal
  963.  
  964. Public      lsort
  965.  
  966. Model Tiny
  967. P186
  968. CodeSeg
  969.  
  970. ;****************** lsort() -- Sort an array of longs
  971. ;void lsort(long *ary, int size);
  972.  
  973. ary         equ bp+6
  974. max         equ bp+4
  975. num         equ bp-4
  976.  
  977. Proc        lsort
  978.  
  979.             enter 4,0               ;Set up stack frame
  980.             pusha                   ;Save all registers
  981.  
  982.             mov bx,[ary]            ;Call recursive routine
  983.             xor cx,cx
  984.             mov dx,[max]
  985.             dec dx
  986.             shl dx,2
  987.             call p1_qsort
  988.  
  989.             popa                    ;Restore registers
  990.             leave                   ;Delete stack frame
  991.             ret 4                   ;Return
  992.  
  993. p1_done:    popa                    ;Restore registers
  994. p1_ret:     ret                     ;Return
  995.  
  996. p1_qsort:   cmp cx,dx               ;One element, return
  997.             je p1_ret
  998.             pusha
  999.  
  1000.             mov ax,dx               ;Two elements, sort them
  1001.             sub ax,cx
  1002.             cmp ax,4
  1003.             jne p1_cont
  1004.  
  1005.             mov si,cx               ;SI, DI = low, high
  1006.             mov di,dx
  1007.  
  1008.             mov dx,[bx+si+2]        ;Check them
  1009.             mov ax,[bx+si]
  1010.             cmp dx,[bx+di+2]
  1011.             jl p1_done
  1012.             jg p1_swap2
  1013.             cmp ax,[bx+di]
  1014.             jle p1_done
  1015.  
  1016. p1_swap2:   xchg ax,[bx+di]         ;Switch them
  1017.             mov [bx+si],ax
  1018.             xchg dx,[bx+di+2]
  1019.             mov [bx+si+2],dx
  1020.             jmp p1_done
  1021.  
  1022. p1_cont:    mov si,cx               ;NUM = middle element
  1023.             add si,dx
  1024.             shr si,3
  1025.             shl si,2
  1026.             mov ax,[bx+si]
  1027.             mov [num],ax
  1028.             mov ax,[bx+si+2]
  1029.             mov [num+2],ax
  1030.  
  1031.             mov si,cx               ;SI = low, DI = high
  1032.             mov di,dx
  1033.  
  1034. p1_loop:    cmp si,dx               ;While [BX+SI] < NUM and
  1035.             jge p1_loop2            ; SI < DX, advance SI
  1036.             mov ax,[num+2]
  1037.             cmp ax,[bx+si+2]
  1038.             jl p1_loop2
  1039.             jg p1_go1
  1040.             mov ax,[num]
  1041.             cmp ax,[bx+si]
  1042.             jle p1_loop2
  1043. p1_go1:     add si,4
  1044.             jmp p1_loop
  1045.  
  1046. p1_loop2:   cmp di,cx               ;While [BX+DI] > NUM and
  1047.             jle p1_cont2            ; DI > CX, advance DI
  1048.             mov ax,[num+2]
  1049.             cmp ax,[bx+di+2]
  1050.             jg p1_cont2
  1051.             jl p1_go2
  1052.             mov ax,[num]
  1053.             cmp ax,[bx+di]
  1054.             jge p1_cont2
  1055. p1_go2:     sub di,4
  1056.             jmp p1_loop2
  1057.  
  1058. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1059.             jge p1_rec
  1060.  
  1061.             push [bx+si]            ;Swap elements
  1062.             push [bx+di]
  1063.             pop [bx+si]
  1064.             pop [bx+di]
  1065.             push [bx+si+2]
  1066.             push [bx+di+2]
  1067.             pop [bx+si+2]
  1068.             pop [bx+di+2]
  1069.             add si,4                ;Advance SI, DI
  1070.             sub di,4
  1071.  
  1072.             jmp p1_loop             ;Loop back
  1073.  
  1074. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1075.             je p1_skip1             ;recurse to sort it
  1076.             xchg dx,di
  1077.             call p1_qsort
  1078.             xchg dx,di
  1079.  
  1080. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1081.             je p1_done2             ;recurse to sort it
  1082.             xchg cx,si
  1083.             call p1_qsort
  1084.             xchg cx,si
  1085.  
  1086. p1_done2:   jmp p1_done             ;Return
  1087.  
  1088. EndP        lsort
  1089.  
  1090. End
  1091.  
  1092. ~~~C_SSORT
  1093. Ideal
  1094.  
  1095. Extrn       strcmp:near
  1096. Public      ssort
  1097.  
  1098. Model Tiny
  1099. P186
  1100. CodeSeg
  1101.  
  1102. ;****************** ssort() -- Sort an array of strings
  1103. ;void ssort(char **ary, int size);
  1104.  
  1105. ary         equ bp+6
  1106. max         equ bp+4
  1107.  
  1108. Proc        ssort
  1109.  
  1110.             push bp                 ;Set up stack frame
  1111.             mov bp,sp
  1112.             pusha                   ;Save all registers
  1113.  
  1114.             mov bx,[ary]            ;Call recursive routine
  1115.             xor cx,cx
  1116.             mov dx,[max]
  1117.             dec dx
  1118.             add dx,dx
  1119.             call p1_qsort
  1120.  
  1121.             popa                    ;Restore registers
  1122.             pop bp                  ;Delete stack frame
  1123.             ret 4                   ;Return
  1124.  
  1125. p1_qsort:   cmp cx,dx               ;One element, return
  1126.             jne $+3
  1127.             ret
  1128.             pusha
  1129.  
  1130.             mov ax,dx               ;Two elements, sort them
  1131.             sub ax,cx
  1132.             cmp ax,2
  1133.             jne p1_cont
  1134.  
  1135.             mov si,cx               ;SI, DI = low, high
  1136.             mov di,dx
  1137.  
  1138.             mov ax,[bx+si]          ;Check them
  1139.             push ax [bx+di]
  1140.             call strcmp
  1141.             test ax,ax
  1142.             jle p1_done
  1143.  
  1144.             push [bx+si]            ;Switch them
  1145.             push [bx+di]
  1146.             pop [bx+si]
  1147.             pop [bx+di]
  1148.             jmp p1_done
  1149.  
  1150. p1_cont:    mov si,cx               ;AX = middle element
  1151.             add si,dx
  1152.             shr si,2
  1153.             add si,si
  1154.             mov ax,[bx+si]
  1155.  
  1156.             mov si,cx               ;SI = low, DI = high
  1157.             mov di,dx
  1158.  
  1159. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1160.             jge p1_loop2            ; SI < DX, advance SI
  1161.             push ax ax [bx+si]
  1162.             call strcmp
  1163.             pop ax
  1164.             jle p1_loop2
  1165.             add si,2
  1166.             jmp p1_loop
  1167.  
  1168. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1169.             jle p1_cont2            ; DI > CX, advance DI
  1170.             push ax ax [bx+di]
  1171.             call strcmp
  1172.             pop ax
  1173.             jge p1_cont2
  1174.             sub di,2
  1175.             jmp p1_loop2
  1176.  
  1177. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1178.             jge p1_rec
  1179.  
  1180.             push [bx+si]            ;Swap elements
  1181.             push [bx+di]
  1182.             pop [bx+si]
  1183.             pop [bx+di]
  1184.             add si,2                ;Advance SI, DI
  1185.             sub di,2
  1186.  
  1187.             jmp p1_loop             ;Loop back
  1188.  
  1189. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1190.             je p1_skip1             ;recurse to sort it
  1191.             xchg dx,di
  1192.             call p1_qsort
  1193.             xchg dx,di
  1194.  
  1195. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1196.             je p1_done              ;recurse to sort it
  1197.             xchg cx,si
  1198.             call p1_qsort
  1199.             xchg cx,si
  1200.  
  1201. p1_done:    popa                    ;Restore registers
  1202. p1_ret:     ret                     ;Return
  1203.  
  1204. EndP        ssort
  1205.  
  1206. End
  1207.  
  1208. ~~~C_XSORT
  1209. Ideal
  1210.  
  1211. Public      xsort
  1212.  
  1213. Model Tiny
  1214. P186
  1215. CodeSeg
  1216.  
  1217. ;****************** xsort() -- Sort array, generalized
  1218. ;void xsort(void **ary, int size, void *func);
  1219.  
  1220. ary         equ bp+8
  1221. max         equ bp+6
  1222. func        equ bp+4
  1223.  
  1224. Proc        xsort
  1225.  
  1226.             push bp                 ;Set up stack frame
  1227.             mov bp,sp
  1228.             pusha                   ;Save all registers
  1229.  
  1230.             mov bx,[ary]            ;Call recursive routine
  1231.             xor cx,cx
  1232.             mov dx,[max]
  1233.             dec dx
  1234.             add dx,dx
  1235.             call p1_qsort
  1236.  
  1237.             popa                    ;Restore registers
  1238.             pop bp                  ;Delete stack frame
  1239.             ret 4                   ;Return
  1240.  
  1241. p1_qsort:   cmp cx,dx               ;One element, return
  1242.             jne $+3
  1243.             ret
  1244.             pusha
  1245.  
  1246.             mov ax,dx               ;Two elements, sort them
  1247.             sub ax,cx
  1248.             cmp ax,2
  1249.             jne p1_cont
  1250.  
  1251.             mov si,cx               ;SI, DI = low, high
  1252.             mov di,dx
  1253.  
  1254.             mov ax,[bx+si]          ;Check them
  1255.             push ax [bx+di]
  1256.             call [word func]
  1257.             test ax,ax
  1258.             jle p1_done
  1259.  
  1260.             push [bx+si]            ;Switch them
  1261.             push [bx+di]
  1262.             pop [bx+si]
  1263.             pop [bx+di]
  1264.             jmp p1_done
  1265.  
  1266. p1_cont:    mov si,cx               ;AX = middle element
  1267.             add si,dx
  1268.             shr si,2
  1269.             add si,si
  1270.             mov ax,[bx+si]
  1271.  
  1272.             mov si,cx               ;SI = low, DI = high
  1273.             mov di,dx
  1274.  
  1275. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1276.             jge p1_loop2            ; SI < DX, advance SI
  1277.             push ax ax [bx+si]
  1278.             call [word func]
  1279.             pop ax
  1280.             jle p1_loop2
  1281.             add si,2
  1282.             jmp p1_loop
  1283.  
  1284. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1285.             jle p1_cont2            ; DI > CX, advance DI
  1286.             push ax ax [bx+di]
  1287.             call [word func]
  1288.             pop ax
  1289.             jge p1_cont2
  1290.             sub di,2
  1291.             jmp p1_loop2
  1292.  
  1293. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1294.             jge p1_rec
  1295.  
  1296.             push [bx+si]            ;Swap elements
  1297.             push [bx+di]
  1298.             pop [bx+si]
  1299.             pop [bx+di]
  1300.             add si,2                ;Advance SI, DI
  1301.             sub di,2
  1302.  
  1303.             jmp p1_loop             ;Loop back
  1304.  
  1305. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1306.             je p1_skip1             ;recurse to sort it
  1307.             xchg dx,di
  1308.             call p1_qsort
  1309.             xchg dx,di
  1310.  
  1311. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1312.             je p1_done              ;recurse to sort it
  1313.             xchg cx,si
  1314.             call p1_qsort
  1315.             xchg cx,si
  1316.  
  1317. p1_done:    popa                    ;Restore registers
  1318. p1_ret:     ret                     ;Return
  1319.  
  1320. EndP        xsort
  1321.  
  1322. End
  1323.  
  1324. ~~~C_LSHL
  1325. Ideal
  1326.  
  1327. Public      lshl
  1328.  
  1329. Model Tiny
  1330. CodeSeg
  1331. P186
  1332.  
  1333. ;****************** lshl() -- Shift long integer to the left
  1334. ;long lshl(long x, int d);    37 clocks (486)
  1335.  
  1336. x           equ bp+6
  1337. d           equ bp+4
  1338.  
  1339. Proc        lshl
  1340.  
  1341.             push bp                 ;Set up stack frame
  1342.             mov bp,sp
  1343.             push cx                 ;Save CX
  1344.  
  1345.             mov ax,[x]              ;DX:AX = x
  1346.             mov dx,[x+2]
  1347.             mov cl,[d]              ;CL = distance
  1348.  
  1349.             cmp cl,16               ;Distance > 16?
  1350.             jb p1_cont              ;Jump if not
  1351.  
  1352.             mov dx,ax               ;Shift left 16
  1353.             xor ax,ax
  1354.  
  1355. p1_cont:    and cl,15               ;Mask off high part
  1356.             push ax cx              ;Save AX, CX
  1357.             shl dx,cl               ;DX = (DX shl CL) +
  1358.             xor cl,15               ;     (AX shr (16 - CL))
  1359.             inc cx
  1360.             shr ax,cl
  1361.             add dx,ax
  1362.             pop cx ax               ;Restore AX, CX
  1363.             shl ax,cl               ;AX = AX shl CL
  1364.  
  1365.             pop cx                  ;Restore CX
  1366.             pop bp                  ;Delete stack frame
  1367.             ret 6                   ;Return
  1368.  
  1369. EndP        lshl
  1370.  
  1371. End
  1372.  
  1373. ~~~C_LSHR
  1374. Ideal
  1375.  
  1376. Public      lshr
  1377.  
  1378. Model Tiny
  1379. CodeSeg
  1380. P186
  1381.  
  1382. ;****************** lshr() -- Shift long integer to the right
  1383. ;long lshr(long x, int d);    37 clocks (486)
  1384.  
  1385. x           equ bp+6
  1386. d           equ bp+4
  1387.  
  1388. Proc        lshr
  1389.  
  1390.             push bp                 ;Set up stack frame
  1391.             mov bp,sp
  1392.             push cx                 ;Save CX
  1393.  
  1394.             mov ax,[x]              ;DX:AX = x
  1395.             mov dx,[x+2]
  1396.             mov cl,[d]              ;CL = distance
  1397.  
  1398.             cmp cl,16               ;Distance > 16?
  1399.             jb p1_cont              ;Jump if not
  1400.  
  1401.             mov ax,dx               ;Shift right 16
  1402.             xor dx,dx
  1403.  
  1404. p1_cont:    and cl,15               ;Mask off high part
  1405.             push dx cx              ;Save DX, CX
  1406.             shr ax,cl               ;AX = (AX shr CL) +
  1407.             xor cl,15               ;     (DX shl (16 - CL))
  1408.             inc cx
  1409.             shl dx,cl
  1410.             add ax,dx
  1411.             pop cx dx               ;Restore DX, CX
  1412.             shr dx,cl               ;DX = DX shr CL
  1413.  
  1414.             pop cx                  ;Restore CX
  1415.             pop bp                  ;Delete stack frame
  1416.             ret 6                   ;Return
  1417.  
  1418. EndP        lshr
  1419.  
  1420. End
  1421.  
  1422. ~~~C_LSAR
  1423. Ideal
  1424.  
  1425. Public      lsar
  1426.  
  1427. Model Tiny
  1428. CodeSeg
  1429. P186
  1430.  
  1431. ;****************** lsar() -- Shift long integer to the right, signed
  1432. ;long lsar(long x, int d);    39 clocks (486)
  1433.  
  1434. x           equ bp+6
  1435. d           equ bp+4
  1436.  
  1437. Proc        lsar
  1438.  
  1439.             push bp                 ;Set up stack frame
  1440.             mov bp,sp
  1441.             push cx                 ;Save CX
  1442.  
  1443.             mov ax,[x]              ;DX:AX = x
  1444.             mov dx,[x+2]
  1445.             mov cl,[d]              ;CL = distance
  1446.  
  1447.             cmp cl,16               ;Distance > 16?
  1448.             jb p1_cont              ;Jump if not
  1449.  
  1450.             mov ax,dx               ;Shift right 16
  1451.             cbw
  1452.  
  1453. p1_cont:    and cl,15               ;Mask off high part
  1454.             push dx cx              ;Save DX, CX
  1455.             shr ax,cl               ;AX = (AX shr CL) +
  1456.             xor cl,15               ;     (DX shl (16 - CL))
  1457.             inc cx
  1458.             shl dx,cl
  1459.             add ax,dx
  1460.             pop cx dx               ;Restore DX, CX
  1461.             sar dx,cl               ;DX = DX sar CL
  1462.  
  1463.             pop cx                  ;Restore CX
  1464.             pop bp                  ;Delete stack frame
  1465.             ret 6                   ;Return
  1466.  
  1467. EndP        lsar
  1468.  
  1469. End
  1470.  
  1471. ~~~C_LMUL
  1472. Ideal
  1473.  
  1474. Public      lmul
  1475.  
  1476. Model Tiny
  1477. CodeSeg
  1478. P186
  1479.  
  1480. ;****************** lmul() -- Multiply long integers
  1481. ;long lmul(long x, long y);   70 clocks (486)
  1482.  
  1483. x           equ bp+8
  1484. y           equ bp+4
  1485.  
  1486. Proc        lmul
  1487.  
  1488.             push bp                 ;Set up stack frame
  1489.             mov bp,sp
  1490.             push bx                 ;Save registers
  1491.  
  1492.             mov ax,[x]              ;Multiply low words
  1493.             mul [word y]
  1494.             mov bx,dx               ;BX = high word
  1495.             push ax                 ;Save low word
  1496.  
  1497.             mov ax,[x+2]            ;Multiply high by low Y
  1498.             mul [word y]
  1499.             add bx,ax               ;Add in result
  1500.  
  1501.             mov ax,[y+2]            ;Multiply high by low X
  1502.             mul [word x]
  1503.             add ax,bx               ;Add in result
  1504.  
  1505.             pop dx                  ;Restore low word
  1506.             xchg dx,ax              ;DX:AX = result
  1507.  
  1508.             pop bx                  ;Restore registers
  1509.             pop bp                  ;Delete stack frame
  1510.             ret 8                   ;Return
  1511.  
  1512. EndP        lmul
  1513.  
  1514. End
  1515.  
  1516. ~~~C_LIMUL
  1517. Ideal
  1518.  
  1519. Public      limul
  1520.  
  1521. Model Tiny
  1522. CodeSeg
  1523. P186
  1524.  
  1525. ;****************** limul() -- Multiply long integers, signed
  1526. ;long limul(long x, long y);   89-97 clocks (486)
  1527.  
  1528. x           equ bp+8
  1529. y           equ bp+4
  1530.  
  1531. Proc        limul
  1532.  
  1533.             push bp                 ;Set up stack frame
  1534.             mov bp,sp
  1535.             push bx cx              ;Save registers
  1536.  
  1537.             xor cx,cx               ;Clear neg flag
  1538.  
  1539.             mov ax,[x+2]            ;AX = x high word
  1540.             test ax,ax              ;Negative?
  1541.             jge p1_xok
  1542.             neg ax                  ;Negate X
  1543.             neg [word x]
  1544.             sbb ax,0
  1545.             not cx                  ;Set neg flag
  1546.  
  1547. p1_xok:     mov [x+2],ax            ;Save X
  1548.  
  1549.             mov ax,[y+2]            ;AX = y high word
  1550.             test ax,ax              ;Negative?
  1551.             jge p1_yok
  1552.             neg ax                  ;Negate Y
  1553.             neg [word y]
  1554.             sbb ax,0
  1555.             not cx                  ;Flip neg flag
  1556.  
  1557. p1_yok:     mov [y+2],ax            ;Save Y
  1558.  
  1559.             mov ax,[x]              ;Multiply low words
  1560.             mul [word y]
  1561.             mov bx,dx               ;BX = high word
  1562.             push ax                 ;Save low word
  1563.  
  1564.             mov ax,[x+2]            ;Multiply high by low Y
  1565.             mul [word y]
  1566.             add bx,ax               ;Add in result
  1567.  
  1568.             mov ax,[y+2]            ;Multiply high by low X
  1569.             mul [word x]
  1570.             add ax,bx               ;Add in result
  1571.  
  1572.             pop dx                  ;Restore low word
  1573.             xchg dx,ax              ;DX:AX = result
  1574.  
  1575.             test cx,cx              ;Check neg flag
  1576.             jz p1_done
  1577.  
  1578.             neg dx                  ;Negate result
  1579.             neg ax
  1580.             sbb dx,0
  1581.  
  1582. p1_done:    pop cx bx               ;Restore registers
  1583.             pop bp                  ;Delete stack frame
  1584.             ret 8                   ;Return
  1585.  
  1586. EndP        limul
  1587.  
  1588. End
  1589.  
  1590. ~~~C_LDIV
  1591. Ideal
  1592.  
  1593. Public      ldiv
  1594.  
  1595. Model Tiny
  1596. CodeSeg
  1597. P186
  1598.  
  1599. ;****************** ldiv() -- Divide long integers
  1600. ;long ldiv(long x, long y);   692-948 clocks (486)
  1601.  
  1602. x           equ bp+8
  1603. y           equ bp+4
  1604.  
  1605. Proc        ldiv
  1606.  
  1607.             push bp                 ;Set up stack frame
  1608.             mov bp,sp
  1609.             push bx cx si           ;Save registers
  1610.  
  1611.             xor ax,ax               ;Clear DX:AX, CX:BX
  1612.             xor bx,bx               ;DX:AX will contain
  1613.             xor cx,cx               ;the result, and
  1614.             xor dx,dx               ;CX:BX will be X.
  1615.             mov si,32               ;SI = count
  1616.  
  1617. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1618.             rcl [word x+2],1
  1619.             adc bx,bx
  1620.             adc cx,cx
  1621.  
  1622.             add ax,ax               ;Shift result left by 1
  1623.             adc dx,dx
  1624.  
  1625.             cmp cx,[y+2]            ;Compare the partial X
  1626.             jb p1_skip              ;to Y, if X is bigger
  1627.             ja p1_sub               ;then Y is subtracted
  1628.             cmp bx,[y]              ;from the partial X.
  1629.             jb p1_skip
  1630.  
  1631. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1632.             sbb cx,[y+2]
  1633.             add ax,1                ;Add one bit to result
  1634.             adc dx,0
  1635.  
  1636. p1_skip:    dec si                  ;Loop back
  1637.             jnz p1_loop
  1638.  
  1639.             pop si cx bx            ;Restore registers
  1640.             pop bp                  ;Delete stack frame
  1641.             ret 8                   ;Return
  1642.  
  1643. EndP        ldiv
  1644.  
  1645. End
  1646.  
  1647. ~~~C_LIDIV
  1648. Ideal
  1649.  
  1650. Public      lidiv
  1651.  
  1652. Model Tiny
  1653. CodeSeg
  1654. P186
  1655.  
  1656. ;****************** lidiv() -- Divide long integers, signed
  1657. ;long lidiv(long x, long y);   711-975 clocks (486)
  1658.  
  1659. x           equ bp+8
  1660. y           equ bp+4
  1661.  
  1662. Proc        lidiv
  1663.  
  1664.             push bp                 ;Set up stack frame
  1665.             mov bp,sp
  1666.             push bx cx si           ;Save registers
  1667.  
  1668.             xor cx,cx               ;Clear neg flag
  1669.  
  1670.             mov ax,[x+2]            ;AX = x high word
  1671.             test ax,ax              ;Negative?
  1672.             jge p1_xok
  1673.             neg ax                  ;Negate X
  1674.             neg [word x]
  1675.             sbb ax,0
  1676.             not cx                  ;Set neg flag
  1677.  
  1678. p1_xok:     mov [x+2],ax            ;Save X
  1679.  
  1680.             mov ax,[y+2]            ;AX = y high word
  1681.             test ax,ax              ;Negative?
  1682.             jge p1_yok
  1683.             neg ax                  ;Negate Y
  1684.             neg [word y]
  1685.             sbb ax,0
  1686.             not cx                  ;Flip neg flag
  1687.  
  1688. p1_yok:     mov [y+2],ax            ;Save Y
  1689.             push cx                 ;Save neg flag
  1690.  
  1691.             xor ax,ax               ;Clear DX:AX, CX:BX
  1692.             xor bx,bx               ;DX:AX will contain
  1693.             xor cx,cx               ;the result, and
  1694.             xor dx,dx               ;CX:BX will be X.
  1695.             mov si,32               ;SI = count
  1696.  
  1697. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1698.             rcl [word x+2],1
  1699.             adc bx,bx
  1700.             adc cx,cx
  1701.  
  1702.             add ax,ax               ;Shift result left by 1
  1703.             adc dx,dx
  1704.  
  1705.             cmp cx,[y+2]            ;Compare the partial X
  1706.             jb p1_skip              ;to Y, if X is bigger
  1707.             ja p1_sub               ;then Y is subtracted
  1708.             cmp bx,[y]              ;from the partial X.
  1709.             jb p1_skip
  1710.  
  1711. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1712.             sbb cx,[y+2]
  1713.             add ax,1                ;Add one bit to result
  1714.             adc dx,0
  1715.  
  1716. p1_skip:    dec si                  ;Loop back
  1717.             jnz p1_loop
  1718.  
  1719.             pop cx                  ;Restore neg flag
  1720.             test cx,cx              ;Check neg flag
  1721.             jz p1_done
  1722.  
  1723.             neg dx                  ;Negate result
  1724.             neg ax
  1725.             sbb dx,0
  1726.  
  1727. p1_done:    pop si cx bx            ;Restore registers
  1728.             pop bp                  ;Delete stack frame
  1729.             ret 8                   ;Return
  1730.  
  1731. EndP        lidiv
  1732.  
  1733. End
  1734.  
  1735. ~~~C_FIXMUL
  1736. Ideal
  1737.  
  1738. Public      fixmul
  1739.  
  1740. Model Tiny
  1741. CodeSeg
  1742. P186
  1743.  
  1744. ;****************** fixmul() -- Multiply fixed point numbers
  1745. ;long fixmul(long x, long y);   101-109 clocks (486)
  1746.  
  1747. x           equ bp+8
  1748. y           equ bp+4
  1749.  
  1750. Proc        fixmul
  1751.  
  1752.             push bp                 ;Set up stack frame
  1753.             mov bp,sp
  1754.             push bx cx si           ;Save registers
  1755.  
  1756.             xor si,si               ;Clear neg flag
  1757.  
  1758.             mov ax,[x+2]            ;AX = x high word
  1759.             test ax,ax              ;Negative?
  1760.             jge p1_xok
  1761.             neg ax                  ;Negate X
  1762.             neg [word x]
  1763.             sbb ax,0
  1764.             not si                  ;Set neg flag
  1765.  
  1766. p1_xok:     mov [x+2],ax            ;Save X
  1767.  
  1768.             mov ax,[y+2]            ;AX = y high word
  1769.             test ax,ax              ;Negative?
  1770.             jge p1_yok
  1771.             neg ax                  ;Negate Y
  1772.             neg [word y]
  1773.             sbb ax,0
  1774.             not si                  ;Flip neg flag
  1775.  
  1776. p1_yok:     mov [y+2],ax            ;Save Y
  1777.  
  1778.             mov ax,[x+2]            ;Multiply high by low Y
  1779.             mul [word y]
  1780.             mov cx,dx               ;Save in CX:BX
  1781.             mov bx,ax
  1782.  
  1783.             mov ax,[y+2]            ;Multiply high by low X
  1784.             mul [word x]
  1785.             add bx,ax               ;Add in result
  1786.             adc cx,dx
  1787.  
  1788.             mov ax,[x]              ;Multiply low words
  1789.             mul [word y]
  1790.             add bx,dx               ;Add in result
  1791.             adc cx,0
  1792.  
  1793.             mov ax,[x+2]            ;Multiply high words
  1794.             mul [word y+2]
  1795.             add ax,cx               ;Add in result
  1796.             mov dx,bx               ;DX:AX = result
  1797.             xchg dx,ax
  1798.  
  1799.             test si,si              ;Check neg flag
  1800.             jz p1_done
  1801.  
  1802.             neg dx                  ;Negate result
  1803.             neg ax
  1804.             sbb dx,0
  1805.  
  1806. p1_done:    pop si cx bx            ;Restore registers
  1807.             pop bp                  ;Delete stack frame
  1808.             ret 8                   ;Return
  1809.  
  1810. EndP        fixmul
  1811.  
  1812. End
  1813.  
  1814. ~~~C_FIXDIV
  1815. Ideal
  1816.  
  1817. Public      fixdiv
  1818.  
  1819. Model Tiny
  1820. CodeSeg
  1821. P186
  1822.  
  1823. ;****************** fixdiv() -- Divide fixed point numbers
  1824. ;long fixdiv(long x, long y);   1028-1412 clocks (486)
  1825.  
  1826. x           equ bp+8
  1827. y           equ bp+4
  1828.  
  1829. Proc        fixdiv
  1830.  
  1831.             push bp                 ;Set up stack frame
  1832.             mov bp,sp
  1833.             push bx cx si           ;Save registers
  1834.  
  1835.             xor cx,cx               ;Clear neg flag
  1836.  
  1837.             mov ax,[x+2]            ;AX = x high word
  1838.             test ax,ax              ;Negative?
  1839.             jge p1_xok
  1840.             neg ax                  ;Negate X
  1841.             neg [word x]
  1842.             sbb ax,0
  1843.             not cx                  ;Set neg flag
  1844.  
  1845. p1_xok:     mov [x+2],ax            ;Save X
  1846.  
  1847.             mov ax,[y+2]            ;AX = y high word
  1848.             test ax,ax              ;Negative?
  1849.             jge p1_yok
  1850.             neg ax                  ;Negate Y
  1851.             neg [word y]
  1852.             sbb ax,0
  1853.             not cx                  ;Flip neg flag
  1854.  
  1855. p1_yok:     mov [y+2],ax            ;Save Y
  1856.             push cx                 ;Save neg flag
  1857.  
  1858.             xor ax,ax               ;Clear DX:AX, CX:BX
  1859.             xor bx,bx               ;DX:AX will contain
  1860.             xor cx,cx               ;the result, and
  1861.             xor dx,dx               ;CX:BX will be X.
  1862.             mov si,48               ;SI = count
  1863.  
  1864. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1865.             rcl [word x+2],1
  1866.             adc bx,bx
  1867.             adc cx,cx
  1868.  
  1869.             add ax,ax               ;Shift result left by 1
  1870.             adc dx,dx
  1871.  
  1872.             cmp cx,[y+2]            ;Compare the partial X
  1873.             jb p1_skip              ;to Y, if X is bigger
  1874.             ja p1_sub               ;then Y is subtracted
  1875.             cmp bx,[y]              ;from the partial X.
  1876.             jb p1_skip
  1877.  
  1878. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1879.             sbb cx,[y+2]
  1880.             add ax,1                ;Add one bit to result
  1881.             adc dx,0
  1882.  
  1883. p1_skip:    dec si                  ;Loop back
  1884.             jnz p1_loop
  1885.  
  1886.             pop cx                  ;Restore neg flag
  1887.             test cx,cx              ;Check neg flag
  1888.             jz p1_done
  1889.  
  1890.             neg dx                  ;Negate result
  1891.             neg ax
  1892.             sbb dx,0
  1893.  
  1894. p1_done:    pop si cx bx            ;Restore registers
  1895.             pop bp                  ;Delete stack frame
  1896.             ret 8                   ;Return
  1897.  
  1898. EndP        fixdiv
  1899.  
  1900. End
  1901.  
  1902. ~~~C_FIXTOA
  1903. Ideal
  1904.  
  1905. Public      fixtoa
  1906.  
  1907. Model Tiny
  1908. CodeSeg
  1909. P186
  1910.  
  1911. ;****************** fixtoa() -- Convert fixed point number to string
  1912. ;void fixtoa(int n, char *strp);
  1913.  
  1914. n           equ bp+6
  1915. strp        equ bp+4
  1916.  
  1917. Proc        fixtoa
  1918.  
  1919.             push bp                 ;Set up stack frame
  1920.             mov bp,sp
  1921.             pusha                   ;Save all registers
  1922.  
  1923.             mov di,[strp]           ;DI = string pointer
  1924.             mov dx,[n+2]            ;DX:AX = n
  1925.             mov ax,[n]
  1926.  
  1927.             test dx,dx              ;Negative?
  1928.             jge p1_noneg
  1929.             mov [byte di],'-'       ;Store minus sign
  1930.             inc di
  1931.             neg dx                  ;Make it positive
  1932.             neg ax
  1933.             sbb dx,0
  1934.  
  1935. p1_noneg:   push dx                 ;Save DX
  1936.             xor bx,bx               ;Zero rem flag
  1937.             add ax,ax               ;Shift out high bit
  1938.             adc bx,0                ;BX = rem flag
  1939.             shr ax,1                ;Restore AX
  1940.  
  1941.             mov cx,50000            ;AX = AX * 50000
  1942.             mul cx
  1943.             shr ax,15               ;AX = AX / 32768
  1944.             shl dx,1
  1945.             or ax,dx
  1946.             pop dx                  ;Restore DX
  1947.             push bx ax              ;Save BX, AX
  1948.  
  1949.             xchg dx,ax              ;Integer part in AX
  1950.  
  1951.             xor cx,cx               ;Zero CX
  1952.             mov si,10               ;SI = 10
  1953.  
  1954. p1_dloop:   xor dx,dx               ;Divide by 10
  1955.             div si
  1956.             mov bl,dl               ;Remainder in BL
  1957.             add bl,30h              ;Convert to digit
  1958.             push bx                 ;Push digit
  1959.             inc cx
  1960.             test ax,ax              ;Loop back
  1961.             jnz p1_dloop
  1962.  
  1963. p1_ploop:   pop ax                  ;Pop digit
  1964.             mov [di],al             ;Store digit
  1965.             inc di
  1966.             loop p1_ploop           ;Loop back
  1967.  
  1968.             mov [byte di],'.'       ;Store decimal point
  1969.             inc di
  1970.             pop ax bx               ;Restore low data
  1971.             xor dx,dx               ;Zero DX
  1972.             test bx,bx              ;Check for high part
  1973.             jz p1_nohigh
  1974.  
  1975.             add ax,50000            ;Add in 50000
  1976.             adc dx,0
  1977.  
  1978. p1_nohigh:  mov si,10               ;SI = 10
  1979.             mov cx,5                ;5 digits
  1980.             jmp p1_skip1
  1981.  
  1982. p1_dloopb:  xor dx,dx               ;Zero DX
  1983. p1_skip1:   div si                  ;Divide by 10
  1984.             mov bl,dl               ;Remainder in BL
  1985.             add bl,30h              ;Convert to digit
  1986.             push bx                 ;Push digit
  1987.             loop p1_dloopb          ;Loop back
  1988.  
  1989.             mov cx,5                ;5 digits
  1990.  
  1991. p1_ploopb:  pop ax                  ;Pop digit
  1992.             mov [di],al             ;Store digit
  1993.             inc di
  1994.             loop p1_ploopb          ;Loop back
  1995.  
  1996.             mov [byte di],0         ;Add the null byte
  1997.  
  1998. p1_done:    popa                    ;Restore registers
  1999.             pop bp                  ;Delete stack frame
  2000.             ret 6                   ;Return
  2001.  
  2002. EndP        fixtoa
  2003.  
  2004. End
  2005.  
  2006. ~~~C_ATOFIX
  2007. Ideal
  2008.  
  2009. Public      atofix
  2010.  
  2011. Model Tiny
  2012. CodeSeg
  2013. P186
  2014.  
  2015. ;****************** atofix() -- Convert string to fixed point number
  2016. ;long atofix(char *strp);
  2017.  
  2018. strp        equ bp+4
  2019.  
  2020. Proc        atofix
  2021.  
  2022.             push bp                 ;Set up stack frame
  2023.             mov bp,sp
  2024.             push bx cx si di bp     ;Save registers
  2025.  
  2026.             mov si,[strp]           ;SI = string
  2027.  
  2028.             xor ax,ax               ;AX = 0
  2029.             xor bh,bh               ;BH = 0
  2030.             mov cx,10               ;CX = 10
  2031.  
  2032. p1_ploop:   mov bl,[si]             ;Load char
  2033.             inc si
  2034.             cmp bl,' '              ;Loop while char is space
  2035.             je p1_ploop             ;(20h, or 09h thru 0Dh)
  2036.             cmp bl,9
  2037.             jna p1_go
  2038.             cmp bl,13
  2039.             jbe p1_ploop
  2040.  
  2041. p1_go:      xor bp,bp               ;BP = 0
  2042.             cmp bl,'+'              ;If char = '+', ignore
  2043.             je p1_loop
  2044.             cmp bl,'-'              ;If char <> '-', keep it
  2045.             jne p1_skip
  2046.             inc bp                  ;Set negative flag
  2047.  
  2048. p1_loop:    mov bl,[si]             ;Load char
  2049.             inc si
  2050.  
  2051. p1_skip:    xor dx,dx               ;Clear DX
  2052.             cmp bl,'.'              ;Decimal point, continue
  2053.             je p1_cont
  2054.             cmp bl,'9'              ;Not a digit, finish
  2055.             ja p1_finish
  2056.             sub bl,'0'
  2057.             jc p1_finish
  2058.  
  2059.             mul cx                  ;Multiply by 10
  2060.             add ax,bx               ;Add in digit...
  2061.             jmp p1_loop             ;Loop back
  2062.  
  2063. p1_cont:    push ax                 ;Save integer part
  2064.             xor ax,ax               ;Zero AX
  2065.             mov di,1                ;DI = 1
  2066.  
  2067. p1_floop:   mov bl,[si]             ;Load char
  2068.             inc si
  2069.  
  2070.             cmp bl,'9'              ;Not a digit, finish
  2071.             ja p1_ffinish
  2072.             sub bl,'0'
  2073.             jc p1_ffinish
  2074.  
  2075.             mul cx                  ;Multiply by 10
  2076.             add ax,bx               ;Add in digit...
  2077.             adc dx,0
  2078.             imul di,10              ;Multiply divisor by 10
  2079.             jnc p1_floop            ;Loop while < 5 digits
  2080.  
  2081.             shr dx,1                ;5 digits, divide by 2
  2082.             rcr ax,1                ;and set DI to 50000
  2083.             mov di,50000            ;instead of 100000
  2084.  
  2085. p1_ffinish: mov dx,ax               ;Multiply by 65536
  2086.             xor ax,ax
  2087.             div di                  ;Divide by 10^digits
  2088.             mov dx,ax               ;Fractional part in DX
  2089.             pop ax                  ;Restore integer part
  2090.  
  2091. p1_finish:  xchg dx,ax              ;DX:AX = number
  2092.  
  2093.             dec bp                  ;Positive, don't negate
  2094.             jl p1_done
  2095.  
  2096.             neg dx                  ;Negate the result
  2097.             neg ax
  2098.             sbb dx,0
  2099.  
  2100. p1_done:    pop bp di si cx bx      ;Restore registers
  2101.             pop bp                  ;Delete stack frame
  2102.             ret 2                   ;Return
  2103.  
  2104. EndP        atofix
  2105.  
  2106. End
  2107.  
  2108. ~~~C_BITS
  2109. Ideal
  2110.  
  2111. Public      bitcnt,highbit
  2112.  
  2113. Model Tiny
  2114. P186
  2115. CodeSeg
  2116.  
  2117. ;****************** bitcnt() -- Count set bits in integer
  2118. ;int bitcnt(int x);
  2119.  
  2120. x           equ bp+4
  2121.  
  2122. Proc        bitcnt
  2123.  
  2124.             push bp                 ;Set up stack frame
  2125.             mov bp,sp
  2126.             push bx cx              ;Save registers
  2127.  
  2128.             xor ax,ax               ;Zero counter
  2129.             mov bx,[x]              ;BX = number
  2130.             mov cx,16               ;16 bits
  2131.  
  2132. p1_loop:    add bx,bx               ;Shift out bit
  2133.             adc ax,0                ;Add if carry
  2134.             loop p1_loop            ;Loop back
  2135.  
  2136.             pop cx bx               ;Restore registers
  2137.             pop bp                  ;Delete stack frame
  2138.             ret 2                   ;Return
  2139.  
  2140. EndP        bitcnt
  2141.  
  2142. ;****************** highbit() -- Find high bit in integer
  2143. ;int highbit(int x);             returns -1 if it was zero
  2144.  
  2145. x           equ bp+4
  2146.  
  2147. Proc        highbit
  2148.  
  2149.             push bp                 ;Set up stack frame
  2150.             mov bp,sp
  2151.             push bx                 ;Save registers
  2152.  
  2153.             mov ax,15               ;Start with bit 15
  2154.             mov bx,[x]              ;BX = number
  2155.  
  2156. p2_loop:    add bx,bx               ;Shift out bit
  2157.             jc p2_done              ;Found a bit?
  2158.             dec ax                  ;Loop back
  2159.             jns p2_loop
  2160.  
  2161. p2_done:    pop bx                  ;Restore registers
  2162.             pop bp                  ;Delete stack frame
  2163.             ret 2                   ;Return
  2164.  
  2165. EndP        highbit
  2166.  
  2167. End
  2168.  
  2169. ~~~C_SQRT
  2170. Ideal
  2171.  
  2172. Public      sqrt
  2173.  
  2174. Model Tiny
  2175. P186
  2176. CodeSeg
  2177.  
  2178. ;****************** sqrt() -- Returns the square root of a
  2179. ;                             long.  Result is an integer.
  2180. ;int sqrt(long num);          60-350 clocks (486)
  2181.  
  2182.  
  2183. num         equ bp+4
  2184.  
  2185. Proc        sqrt
  2186.  
  2187.             push bp                 ;Set up stack frame
  2188.             mov bp,sp
  2189.             push cx dx              ;Save registers
  2190.  
  2191.             mov ax,[num]            ;DX:AX = num
  2192.             mov dx,[num+2]
  2193.  
  2194.             mov cx,32               ;32 bits
  2195.  
  2196. p1_bloop:   add ax,ax               ;Find the highest set bit
  2197.             adc dx,dx
  2198.             jc p1_gotbit
  2199.             loop p1_bloop
  2200.  
  2201. p1_gotbit:  mov ax,1                ;CX = first guess 2^(log2(n)/2)
  2202.             shr cx,1
  2203.             shl ax,cl
  2204.             mov cx,ax
  2205.  
  2206. p1_loop:    mov ax,[num]            ;DX:AX = num
  2207.             mov dx,[num+2]
  2208.             div cx                  ;AX = num/guess
  2209.             add cx,ax               ;CX = (guess+(num/guess))/2
  2210.             shr cx,1
  2211.             sub ax,cx               ;If the difference is 1
  2212.             cmp ax,1                ;or less, then done
  2213.             ja p1_loop              ;Loop back
  2214.  
  2215.             mov ax,cx               ;AX = result
  2216.             pop dx cx               ;Restore registers
  2217.             pop bp                  ;Delete stack frame
  2218.             ret 4                   ;Return
  2219.  
  2220. EndP        sqrt
  2221.  
  2222. End
  2223.